package com.ssy.lingxi.member.merchant.serviceimpl.web;

import com.ssy.lingxi.common.constant.member.MemberStatusEnum;
import com.ssy.lingxi.common.constant.member.MemberTypeEnum;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.common.utils.DateTimeUtil;
import com.ssy.lingxi.member.merchant.config.ServiceConfig;
import com.ssy.lingxi.member.merchant.entity.MemberDO;
import com.ssy.lingxi.member.merchant.entity.MemberInspectDO;
import com.ssy.lingxi.member.merchant.entity.MemberRelationDO;
import com.ssy.lingxi.member.merchant.entity.MemberUserDO;
import com.ssy.lingxi.member.merchant.model.constant.MemberInspectSourceEnum;
import com.ssy.lingxi.member.merchant.model.constant.MemberInspectTypeEnum;
import com.ssy.lingxi.member.merchant.model.constant.MemberOuterStatusEnum;
import com.ssy.lingxi.member.merchant.model.vo.basic.request.NamePageVO;
import com.ssy.lingxi.member.merchant.model.vo.basic.request.UserPageVO;
import com.ssy.lingxi.member.merchant.model.vo.basic.response.DropdownItem;
import com.ssy.lingxi.member.merchant.model.vo.basic.response.UserQueryVO;
import com.ssy.lingxi.member.merchant.model.vo.lifecycle.request.CommonIdVO;
import com.ssy.lingxi.member.merchant.model.vo.lifecycle.request.MemberInspectAddVO;
import com.ssy.lingxi.member.merchant.model.vo.lifecycle.request.MemberInspectPageVO;
import com.ssy.lingxi.member.merchant.model.vo.lifecycle.request.MemberInspectUpdateVO;
import com.ssy.lingxi.member.merchant.model.vo.lifecycle.response.MemberInspectPageQueryVO;
import com.ssy.lingxi.member.merchant.model.vo.lifecycle.response.MemberInspectVO;
import com.ssy.lingxi.member.merchant.model.vo.lifecycle.response.MemberRecordInspectPageQueryVO;
import com.ssy.lingxi.member.merchant.model.vo.lifecycle.response.SubMemberQueryVO;
import com.ssy.lingxi.member.merchant.repository.MemberInspectRepository;
import com.ssy.lingxi.member.merchant.repository.MemberRelationRepository;
import com.ssy.lingxi.member.merchant.repository.MemberUserRepository;
import com.ssy.lingxi.member.merchant.service.base.IBaseMemberCacheService;
import com.ssy.lingxi.member.merchant.service.base.IBaseUserDetailService;
import com.ssy.lingxi.member.merchant.service.web.IMemberInspectService;
import com.ssy.lingxi.member.merchant.utils.FileObjectUtil;
import com.ssy.lingxi.member.merchant.utils.NumberUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 会员考察服务实现类
 * @author yzc
 * @version 2.0.0
 * @date 2021/5/17
 */
@Service
public class MemberInspectServiceImpl implements IMemberInspectService {

    @Resource
    private IBaseMemberCacheService memberCacheService;

    @Resource
    private MemberInspectRepository memberInspectRepository;

    @Resource
    private MemberRelationRepository relationRepository;

    @Resource
    private MemberUserRepository memberUserRepository;

    @Resource
    private IBaseUserDetailService baseUserDetailService;


    /**
     * 获取“考察类型”下拉框条件
     *
     * @param headers Http头部信息
     * @return 查询结果
     */
    @Override
    public Wrapper<List<DropdownItem>> getPageConditions(HttpHeaders headers) {
        return Wrapper.success(MemberInspectTypeEnum.toDropdownItems());
    }

    /**
     * “新增会员审查” - 选择下级会员
     *
     * @param headers Http头部信息
     * @param pageVO  接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<SubMemberQueryVO>> pageSubMembers(HttpHeaders headers, NamePageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("id").ascending());
        Specification<MemberRelationDO> specification = (Specification<MemberRelationDO>) (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("memberId").as(Long.class), loginUser.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("roleId").as(Long.class), loginUser.getMemberRoleId()));
            list.add(criteriaBuilder.equal(root.get("status").as(Integer.class), MemberStatusEnum.NORMAL.getCode()));

            // 已入库会员
            List<Integer> outerStatusList = MemberOuterStatusEnum.depositOuterStatus().stream().map(MemberOuterStatusEnum::getCode).collect(Collectors.toList());
            list.add(criteriaBuilder.and(root.get("outerStatus").as(Integer.class).in(outerStatusList)));
            if(StringUtils.hasLength(pageVO.getName())) {
                Join<MemberRelationDO, MemberDO> subMemberJoin = root.join("subMember", JoinType.LEFT);
                list.add(criteriaBuilder.like(subMemberJoin.get("name").as(String.class), "%" + pageVO.getName().trim() + "%"));
            }
            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        Page<MemberRelationDO> pageList = relationRepository.findAll(specification, page);
        return Wrapper.success(new PageData<>(pageList.getTotalElements(), pageList.stream().map(p -> {
            SubMemberQueryVO queryVO = new SubMemberQueryVO();
            queryVO.setSubMemberId(p.getSubMemberId());
            queryVO.setSubRoleId(p.getSubRoleId());
            queryVO.setName(p.getSubMember().getName());
            queryVO.setRoleName(p.getSubRole().getRoleName());
            queryVO.setMemberTypeName(MemberTypeEnum.getCodeMessage(p.getSubRole().getMemberType().getTypeEnum()));
            queryVO.setLevel(p.getLevelRight().getLevel());
            queryVO.setLevelTag(p.getLevelRight().getLevelTag());
            return queryVO;
        }).collect(Collectors.toList())));
    }

    /**
     * “新增或修改会员审查” - 选择用户
     *
     * @param headers Http头部信息
     * @param pageVO  接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<UserQueryVO>> pageUsers(HttpHeaders headers, UserPageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        return baseUserDetailService.pageUsers(loginUser.getMemberId(), pageVO.getName(), pageVO.getOrgName(), pageVO.getJobTitle(), pageVO.getCurrent(), pageVO.getPageSize(), true);
    }

    /**
     * 分页查询会员考察
     * @param headers Http头部信息
     * @param pageVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<MemberInspectPageQueryVO>> pageMemberInspect(HttpHeaders headers, MemberInspectPageVO pageVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("createTime").descending());

        Page<MemberInspectDO> pageList = memberInspectRepository.findAll((Specification<MemberInspectDO>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();
            predicateList.add(cb.equal(root.get("memberId"), loginUser.getMemberId()));
            predicateList.add(cb.equal(root.get("roleId"), loginUser.getMemberRoleId()));
            if (NumberUtil.notNullOrZero(pageVO.getInspectType())) {
                predicateList.add(cb.equal(root.get("inspectType").as(Integer.class), pageVO.getInspectType()));
            }
            if (StringUtils.hasLength(pageVO.getSubject())) {
                predicateList.add(cb.like(root.get("subject").as(String.class), "%" + pageVO.getSubject().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getName())) {
                Join<MemberInspectDO, MemberDO> subMemberJoin = root.join("subMember", JoinType.LEFT);
                predicateList.add(cb.like(subMemberJoin.get("name").as(String.class), "%" + pageVO.getName() + "%"));
            }

            Predicate[] p = new Predicate[predicateList.size()];
            return cb.and(predicateList.toArray(p));
        }, page);

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), pageList.getContent().stream().map(memberInspectDO -> {
            MemberInspectPageQueryVO queryVO = new MemberInspectPageQueryVO();
            queryVO.setId(memberInspectDO.getId());
            queryVO.setName(memberInspectDO.getSubMember().getName());
            queryVO.setSubject(memberInspectDO.getSubject());
            queryVO.setInspectType(memberInspectDO.getInspectType());
            queryVO.setInspectTypeName(MemberInspectTypeEnum.getMsgByCode(memberInspectDO.getInspectType()));
            queryVO.setInspectTime(DateTimeUtil.formatDate(memberInspectDO.getInspectTime()));
            //保留两位小数，小数部分是0的话保留整数，小数第一位不是0的话则保留一位
            queryVO.setScore(ServiceConfig.BIG_DECIMAL_FORMAT.format(memberInspectDO.getScore()));
            queryVO.setResult(memberInspectDO.getResult());
            queryVO.setUpdateOrDel(memberInspectDO.getSource().equals(MemberInspectSourceEnum.BY_MEMBER_ABILITY.getCode()));
            return queryVO;
        }).collect(Collectors.toList())));
    }

    /**
     * 会员信息 - 会员详情 - 分页查询会员考察
     *
     * @param memberId  上级会员Id
     * @param roleId    上级会员角色Id
     * @param subMember 下级会员
     * @param subRoleId 下级会员角色Id
     * @param current   当前页
     * @param pageSize  每页行数
     * @return 查询结果
     */
    @Override
    public Wrapper<PageData<MemberRecordInspectPageQueryVO>> pageMemberInspect(Long memberId, Long roleId, MemberDO subMember, Long subRoleId, int current, int pageSize) {
        Pageable page = PageRequest.of(current - 1, pageSize, Sort.by("createTime").descending());
        Page<MemberInspectDO> pageList = memberInspectRepository.findAll((Specification<MemberInspectDO>) (root, query, cb) -> {
            List<Predicate> predicateList = new ArrayList<>();
            predicateList.add(cb.equal(root.get("memberId").as(Long.class), memberId));
            predicateList.add(cb.equal(root.get("roleId").as(Long.class), roleId));
            predicateList.add(cb.equal(root.get("subMember").as(MemberDO.class), subMember));
            predicateList.add(cb.equal(root.get("subRoleId").as(Long.class), subRoleId));
            Predicate[] p = new Predicate[predicateList.size()];
            return cb.and(predicateList.toArray(p));
        }, page);

        return Wrapper.success(new PageData<>(pageList.getTotalElements(), pageList.getContent().stream().map(memberInspectDO -> {
            MemberRecordInspectPageQueryVO queryVO = new MemberRecordInspectPageQueryVO();
            queryVO.setSubject(memberInspectDO.getSubject());
            queryVO.setInspectType(memberInspectDO.getInspectType());
            queryVO.setInspectTypeName(MemberInspectTypeEnum.getMsgByCode(memberInspectDO.getInspectType()));
            queryVO.setInspectTime(DateTimeUtil.formatDate(memberInspectDO.getInspectTime()));
            //保留两位小数，小数部分是0的话保留整数，小数第一位不是0的话则保留一位
            queryVO.setScore(memberInspectDO.getScore() == null ? "" : ServiceConfig.BIG_DECIMAL_FORMAT.format(memberInspectDO.getScore()));
            return queryVO;
        }).collect(Collectors.toList())));
    }

    /**
     * 新增会员考察
     * @param headers Http头部信息
     * @param addVO 接口参数
     * @return 新增结果
     */
    @Override
    public Wrapper<Void> addMemberInspect(HttpHeaders headers, MemberInspectAddVO addVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberRelationDO relationDO = relationRepository.findFirstByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(loginUser.getMemberId(), loginUser.getMemberRoleId(), addVO.getSubMemberId(), addVO.getSubRoleId());
        if(relationDO == null || !relationDO.getMemberId().equals(loginUser.getMemberId()) || !relationDO.getRoleId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_RELATION_DOES_NOT_EXIST);
        }

        MemberInspectDO memberInspectDO = new MemberInspectDO();
        // 系统用户和编辑用户的差异保存
        if (!NumberUtil.isNullOrZero(addVO.getUserId())) {
            MemberUserDO userDO = memberUserRepository.findById(addVO.getUserId()).orElse(null);
            if (userDO == null) {
                return Wrapper.fail(ResponseCode.MC_MS_MEMBER_USER_DOES_NOT_EXIST);
            }

            memberInspectDO.setByUser(userDO);
        } else {
            memberInspectDO.setByUserEditName(addVO.getUserEditName());
        }

        memberInspectDO.setCreateTime(LocalDateTime.now());
        memberInspectDO.setInspectTime(DateTimeUtil.parseConcatDateTime(addVO.getInspectDay()));
        memberInspectDO.setSource(MemberInspectSourceEnum.BY_MEMBER_ABILITY.getCode());
        memberInspectDO.setMemberId(loginUser.getMemberId());
        memberInspectDO.setRoleId(loginUser.getMemberRoleId());
        memberInspectDO.setSubMember(relationDO.getSubMember());
        memberInspectDO.setSubRoleId(relationDO.getSubRoleId());
        memberInspectDO.setSubject(addVO.getSubject().trim());
        memberInspectDO.setInspectType(addVO.getInspectType());
        memberInspectDO.setReason(StringUtils.hasText(addVO.getReason()) ? addVO.getReason().trim() : "");
        memberInspectDO.setAttachments(FileObjectUtil.toBOList(addVO.getAttachments()));
        memberInspectDO.setScore(addVO.getScore());
        memberInspectDO.setResult(addVO.getResult());
        memberInspectDO.setReports(FileObjectUtil.toBOList(addVO.getReports()));

        memberInspectRepository.saveAndFlush(memberInspectDO);

        return Wrapper.success();
    }

    /**
     * 查询会员考察详情
     * @param headers Http头部信息
     * @param idVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<MemberInspectVO> getMemberInspect(HttpHeaders headers, CommonIdVO idVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberInspectDO memberInspectDO = memberInspectRepository.findById(idVO.getId()).orElse(null);
        if (memberInspectDO == null || !memberInspectDO.getMemberId().equals(loginUser.getMemberId()) || !memberInspectDO.getRoleId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_INSPECTION_DOES_NOT_EXIST);
        }

        MemberInspectVO memberInspectVO = new MemberInspectVO();
        memberInspectVO.setId(memberInspectDO.getId());
        memberInspectVO.setSubMemberId(memberInspectDO.getSubMember().getId());
        memberInspectVO.setSubRoleId(memberInspectDO.getSubRoleId());
        memberInspectVO.setName(memberInspectDO.getSubMember().getName());
        memberInspectVO.setSubject(memberInspectDO.getSubject());
        memberInspectVO.setInspectType(memberInspectDO.getInspectType());
        memberInspectVO.setInspectTypeName(MemberInspectTypeEnum.getMsgByCode(memberInspectDO.getInspectType()));
        memberInspectVO.setInspectDay(DateTimeUtil.formatDate(memberInspectDO.getInspectTime()));
        memberInspectVO.setUserId(memberInspectDO.getByUser().getId());
        memberInspectVO.setUserName(memberInspectDO.getByUser() == null ? "" : memberInspectDO.getByUser().getName());
        memberInspectVO.setReason(memberInspectDO.getReason());
        memberInspectVO.setAttachments(FileObjectUtil.toVOList(memberInspectDO.getAttachments()));
        memberInspectVO.setScore(ServiceConfig.BIG_DECIMAL_FORMAT.format(memberInspectDO.getScore()));
        memberInspectVO.setResult(memberInspectDO.getResult());
        memberInspectVO.setReports(FileObjectUtil.toVOList(memberInspectDO.getReports()));

        return Wrapper.success(memberInspectVO);
    }

    /**
     * 修改会员考察
     * @param headers Http头部信息
     * @param updateVO 接口参数
     * @return 修改结果
     */
    @Override
    public Wrapper<Void> updateMemberInspect(HttpHeaders headers, MemberInspectUpdateVO updateVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberInspectDO memberInspectDO = memberInspectRepository.findById(updateVO.getId()).orElse(null);
        if (Objects.isNull(memberInspectDO) || !memberInspectDO.getMemberId().equals(loginUser.getMemberId()) || !memberInspectDO.getRoleId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_INSPECTION_DOES_NOT_EXIST);
        }

        // 会员审核相关流程生成的数据不予许修改
        if(!memberInspectDO.getSource().equals(MemberInspectSourceEnum.BY_MEMBER_ABILITY.getCode())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_INSPECTION_CAN_NOT_UPDATE);
        }

        MemberRelationDO relationDO = relationRepository.findFirstByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(loginUser.getMemberId(), loginUser.getMemberRoleId(), updateVO.getSubMemberId(), updateVO.getSubRoleId());
        if(relationDO == null || !relationDO.getMemberId().equals(loginUser.getMemberId()) || !relationDO.getRoleId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_RELATION_DOES_NOT_EXIST);
        }

        // 系统用户和编辑用户的差异保存
        if (!NumberUtil.isNullOrZero(updateVO.getUserId())) {
            MemberUserDO userDO = memberUserRepository.findById(updateVO.getUserId()).orElse(null);
            if (userDO == null) {
                return Wrapper.fail(ResponseCode.MC_MS_MEMBER_USER_DOES_NOT_EXIST);
            }

            memberInspectDO.setByUser(userDO);
            memberInspectDO.setByUserEditName(null);
        } else {
            memberInspectDO.setByUser(null);
            memberInspectDO.setByUserEditName(updateVO.getUserEditName());
        }

        memberInspectDO.setCreateTime(LocalDateTime.now());
        memberInspectDO.setInspectTime(DateTimeUtil.parseConcatDateTime(updateVO.getInspectDay()));
        memberInspectDO.setSubMember(relationDO.getSubMember());
        memberInspectDO.setSubRoleId(relationDO.getSubRoleId());
        memberInspectDO.setSubject(updateVO.getSubject().trim());
        memberInspectDO.setInspectType(updateVO.getInspectType());
        memberInspectDO.setReason(StringUtils.hasText(updateVO.getReason()) ? updateVO.getReason().trim() : "");
        memberInspectDO.setAttachments(FileObjectUtil.toBOList(updateVO.getAttachments()));
        memberInspectDO.setScore(updateVO.getScore());
        memberInspectDO.setResult(updateVO.getResult());
        memberInspectDO.setReports(FileObjectUtil.toBOList(updateVO.getReports()));

        memberInspectRepository.saveAndFlush(memberInspectDO);

        return Wrapper.success();
    }

    /**
     * 删除会员考察
     * @param headers Http头部信息
     * @param idVO 接口参数
     * @return 删除结果
     */
    @Override
    public Wrapper<Void> deleteMemberInspect(HttpHeaders headers, CommonIdVO idVO) {
        UserLoginCacheDTO loginUser = memberCacheService.needLoginFromBusinessPlatform(headers);
        MemberInspectDO memberInspectDO = memberInspectRepository.findById(idVO.getId()).orElse(null);
        if (Objects.isNull(memberInspectDO) || !memberInspectDO.getMemberId().equals(loginUser.getMemberId()) || !memberInspectDO.getRoleId().equals(loginUser.getMemberRoleId())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_INSPECTION_DOES_NOT_EXIST);
        }

        // 会员审核相关流程生成的数据不予许删除
        if(!memberInspectDO.getSource().equals(MemberInspectSourceEnum.BY_MEMBER_ABILITY.getCode())) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_INSPECTION_CAN_NOT_DELETE);
        }

        memberInspectRepository.delete(memberInspectDO);

        return Wrapper.success();
    }

}
